import { BufferGeometry, BufferAttribute } from 'three'

const vertices = [
    // front
    { pos: [-1, -1, 1], norm: [0, 0, 1], uv: [0, 0] },
    { pos: [1, -1, 1], norm: [0, 0, 1], uv: [1, 0] },
    { pos: [-1, 1, 1], norm: [0, 0, 1], uv: [0, 1] },

    { pos: [-1, 1, 1], norm: [0, 0, 1], uv: [0, 1] },
    { pos: [1, -1, 1], norm: [0, 0, 1], uv: [1, 0] },
    { pos: [1, 1, 1], norm: [0, 0, 1], uv: [1, 1] },

    // right
    { pos: [1, -1, 1], norm: [1, 0, 0], uv: [0, 0] },
    { pos: [1, -1, -1], norm: [1, 0, 0], uv: [1, 0] },
    { pos: [1, 1, 1], norm: [1, 0, 0], uv: [0, 1] },

    { pos: [1, 1, 1], norm: [1, 0, 0], uv: [0, 1] },
    { pos: [1, -1, -1], norm: [1, 0, 0], uv: [1, 0] },
    { pos: [1, 1, -1], norm: [1, 0, 0], uv: [1, 1] },
    // back
    { pos: [1, -1, -1], norm: [0, 0, -1], uv: [0, 0] },
    { pos: [-1, -1, -1], norm: [0, 0, -1], uv: [1, 0] },
    { pos: [1, 1, -1], norm: [0, 0, -1], uv: [0, 1] },

    { pos: [1, 1, -1], norm: [0, 0, -1], uv: [0, 1] },
    { pos: [-1, -1, -1], norm: [0, 0, -1], uv: [1, 0] },
    { pos: [-1, 1, -1], norm: [0, 0, -1], uv: [1, 1] },
    // left
    { pos: [-1, -1, -1], norm: [-1, 0, 0], uv: [0, 0] },
    { pos: [-1, -1, 1], norm: [-1, 0, 0], uv: [1, 0] },
    { pos: [-1, 1, -1], norm: [-1, 0, 0], uv: [0, 1] },

    { pos: [-1, 1, -1], norm: [-1, 0, 0], uv: [0, 1] },
    { pos: [-1, -1, 1], norm: [-1, 0, 0], uv: [1, 0] },
    { pos: [-1, 1, 1], norm: [-1, 0, 0], uv: [1, 1] },
    // top
    { pos: [1, 1, -1], norm: [0, 1, 0], uv: [0, 0] },
    { pos: [-1, 1, -1], norm: [0, 1, 0], uv: [1, 0] },
    { pos: [1, 1, 1], norm: [0, 1, 0], uv: [0, 1] },

    { pos: [1, 1, 1], norm: [0, 1, 0], uv: [0, 1] },
    { pos: [-1, 1, -1], norm: [0, 1, 0], uv: [1, 0] },
    { pos: [-1, 1, 1], norm: [0, 1, 0], uv: [1, 1] },
    // bottom
    { pos: [1, -1, 1], norm: [0, -1, 0], uv: [0, 0] },
    { pos: [-1, -1, 1], norm: [0, -1, 0], uv: [1, 0] },
    { pos: [1, -1, -1], norm: [0, -1, 0], uv: [0, 1] },

    { pos: [1, -1, -1], norm: [0, -1, 0], uv: [0, 1] },
    { pos: [-1, -1, 1], norm: [0, -1, 0], uv: [1, 0] },
    { pos: [-1, -1, -1], norm: [0, -1, 0], uv: [1, 1] },
];

export default class BoxGeo {

    positionNumComponents = 3;
    normalNumComponents = 3;
    uvNumComponents = 2;

    geometry: BufferGeometry;

    constructor(uv = false) {
        this.geometry = new BufferGeometry();
        let positions: number[] = [];
        let normals: number[] = [];
        let uvs: number[] = [];
        let elements: number[] = [];
        if (uv) {
            for (const vertex of vertices) {
                positions.push(...vertex.pos)
                normals.push(...vertex.norm)
                uvs.push(...vertex.uv)
            }
            elements = [
                0, 1, 2, 3, 4, 5,
                6, 7, 8, 9, 10, 11,
                12, 13, 14, 15, 16, 17,
                18, 19, 20, 21, 22, 23,
                24, 25, 26, 27, 28, 29,
                30, 31, 32, 33, 34, 35,
            ];
        } else {
            const r = 1;
            positions = [
                -r, r, -r,
                -r, r, r,
                r, r, r,
                r, r, -r,

                -r, r, r,
                -r, -r, r,
                r, - r, r,
                r, r, r,

                -r, -r, -r,
                -r, -r, r,
                r, -r, r,
                r, -r, -r,

                -r, -r, -r,
                -r, r, -r,
                r, r, -r,
                r, -r, -r,

                -r, r, -r,
                -r, -r, -r,
                -r, -r, r,
                -r, r, r,

                r, r, r,
                r, -r, r,
                r, -r, -r,
                r, r, -r,
            ];
            elements = [
                0, 1, 2, 0, 2, 3,
                4, 5, 6, 4, 6, 7,
                8, 9, 10, 8, 10, 11,
                12, 13, 14, 12, 14, 15,
                16, 17, 18, 16, 18, 19,
                20, 21, 22, 20, 22, 23,
            ];
            // normals = [
            //     0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
            //     0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,
            //     0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,
            //     0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1,
            //     -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,
            //     1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
            // ];
        }
        this._setAttrib(positions, normals, uvs, elements);
    }

    _setAttrib(positions: number[], normals: number[], uvs: number[], element: number[]) {
        const {
            positionNumComponents, normalNumComponents, uvNumComponents,
            geometry,
        } = this;

        const positionAttr = new BufferAttribute(new Float32Array(positions), positionNumComponents);
        const normalAttr = new BufferAttribute(new Float32Array(normals), normalNumComponents);
        const uvAttr = new BufferAttribute(new Float32Array(uvs), uvNumComponents);
        geometry.setAttribute("position", positionAttr);
        //geometry.setAttribute("normal", normalAttr)
        geometry.setAttribute("uv", uvAttr);
        geometry.setIndex(element);

        //计算法线(该函数会自动根据面来计算出顶点法线,不需要在传入normal)
        //这个计算法线好像有点问题? 底部的法线上反的
        normals.length == 0 ? geometry.computeVertexNormals() : geometry.setAttribute("normal", normalAttr);
    }

    getGeo() {
        return this.geometry;
    }
}